import { ref, toRaw } from "vue";
import { defineStore } from "pinia";
import type { RouteRecordRaw } from "vue-router";
import { constantRoutes } from "@/router";
import Layout from "@/layout/index.vue";
import ParentView from "@/components/ParentView/index.vue";
import { getUserRoutes, type MenuItem } from "@/apis";

import { mapTree } from "xe-utils";
import { transformPathToName } from "@/utils";

// 匹配views里面所有的.vue文件
const modules = import.meta.glob("@/views/**/*.vue");

/** 加载模块 */
export const loadView = (view: string) => {
  let res;
  for (const path in modules) {
    const dir = path.split("views/")[1].split(".vue")[0];
    if (dir === view) {
      res = () => modules[path]();
    }
  }
  return res;
};

/** 将component由字符串转成真正的模块 */
const transformComponentView = (component: string) => {
  if (component === "Layout") {
    return Layout as never;
  } else if (component === "ParentView") {
    return ParentView as never;
  } else {
    return loadView(component) as never;
  }
};

/**
 * @description 前端来做排序、格式化
 * @params {menus} 后端返回的路由数据，已经根据当前用户角色过滤掉了没权限的路由
 * 1. 对后端返回的路由数据进行排序，格式化
 * 2. 同时将component由字符串转成真正的模块
 */
const formatAsyncRoutes = (menus: MenuItem[]) => {
  if (!menus.length) return [];
  menus.sort((a, b) => (a?.menuSort ?? 0) - (b?.menuSort ?? 0)); // 排序
  const routes = mapTree(menus, item => {
    if (item.children && item.children.length) {
      item.children.sort((a, b) => (a?.menuSort ?? 0) - (b?.menuSort ?? 0)); // 排序
    }
    return {
      path: `/${item.path}`,
      name: transformPathToName(item.path),
      componentUrl: item.component,
      component: transformComponentView(item.component),
      meta: {
        title: item.menuName,
        icon: item.icon,
        svgIcon: item.icon,
        hidden: !item.visible,
        keepAlive: item.isCache
      }
    };
  });
  return routes as RouteRecordRaw[];
};

const storeSetup = () => {
  // 所有路由(常驻路由 + 动态路由)
  const routes = ref<RouteRecordRaw[]>([]);
  // 动态路由(异步路由)
  const asyncRoutes = ref<RouteRecordRaw[]>([]);

  /**
   * 合并路由
   * @param data
   */
  const setRoutes = (data: RouteRecordRaw[]) => {
    routes.value = constantRoutes.concat(data);
    asyncRoutes.value = data;
  };

  /**
   * 生成路由
   */
  const generateRoutes = (): Promise<RouteRecordRaw[]> => {
    return new Promise(resolve => {
      // 向后端请求路由数据 这个接口已经根据用户角色过滤了没权限的路由(后端根据用户角色过滤路由显得比较安全些)
      getUserRoutes().then(res => {
        const asyncRoutes = formatAsyncRoutes(res.data);
        setRoutes(asyncRoutes);
        resolve(asyncRoutes);
      });
    });
  };

  return {
    routes,
    asyncRoutes,
    generateRoutes
  };
};

export const useRouteStore = defineStore("route", storeSetup, { persist: true });
